<html>
<head>
	<meta http-equiv=Content-Type content="text/html;charset=utf-8">
	<link rel="stylesheet" type="text/css" href="static/css/menu_bottom-right.css" media="all">
	<title>Functions for scRNA-seq analysis and plot (Seurat)</title>
<style>
/* css version change
v0.1 add FeaturePlot2
*/

pre{
	word-wrap: break-word!important; 
	white-space: pre-wrap;
	padding: 0 10px;
}

h2{
	border-top: 1px solid black;
	padding-left: 5px;
	padding-bottom:0;
	margin-bottom:0;
	color:#999;
	font-family:"微软雅黑"
}


h1{
	border-top: 3px solid black;
	padding-left: 5px;
	padding-bottom:0;
	margin-bottom:0;
	font-family:"微软雅黑"
}

.red{color:red;}

.desc{border:2px dashed #ddd; background:#efefef; padding:10px;}
</style>
</head>



<body>
<h1>Functions for scRNA-seq analysis and plot (Seurat)</h1>

<p>version
<!-- html
0.1 20240411 init single html version
0.2 20240508 Add R file which can be used in R and shown on html directly
0.3 20240527 Add menu_bottom-right.css
0.4 20240531 create bottom right menu after loading R code
-->
0.5 20241115 add header 1
</p>


<pre class="desc">
代码显示流程：
- 本页代码读取自 <b class=red>code/Functions.R</b>
- 代码中所有 &lt; 会被替换为 &amplt;
- 代码中所有 ##{** xx **}## 会被替换为 html 二级标题 &lt;h2&gt; xx &lt;/h2&gt;
- 代码中所有 ##{* xx *}## 会被替换为 html 一级标题 &lt;h1&gt; xx &lt;/h1&gt;

代码书写建议：
- 记录版本变更 编号和理由，R和本html的更新记录到各自文件顶部，html只显示最新记录。
- 代码给出运行实例，加上if(0)防止载入时运行。
</pre>





<pre>
<div id=main_code></div>
</pre>

</body>
</html>




<script>
// ################## tools ################## //

function $(s){
	return document.getElementById(s);
}

/** 返回创建的dom元素
* 只有第一个参数是必须的。
* 其余2个参数可选。
*/
function createElement(tag, json, innerHTML){
	var json=json||{};
	var dom=document.createElement(tag);
	
	if(json!=undefined){
		for(var key in json){
			dom.setAttribute(key,json[key]);
		}
	}
	
	if(innerHTML!=undefined){
		dom.innerHTML=innerHTML;
	}
	return dom;
}

function ajax(url, success){
	var xhr = new XMLHttpRequest();
	xhr.open('GET', url, true);
	xhr.onload = function() {
	  if (this.status == 200) {
		var response = this.responseText;
		success(response);
	  }
	};
	xhr.send();
}

function addEvent(obj,ev,fn){
	if(obj.addEventListener){
		//ff:addEventListener
		obj.addEventListener(ev,fn,false);
	}else{
		//IE:attachEvent
		obj.attachEvent('on'+ev,fn);
	}
}



// ################## local function ################## //
// global parameters here
window.jslecture={
};



//生成右侧菜单
var createRightMenu=function(){
	//0.创建一个侧边栏 虚拟dom
	var oBox=document.createElement("div");
	oBox.setAttribute('id', "rightMenu");

	//设置最大高度为窗口的90%，或 当前窗口高度-20
	var height90=parseInt(document.documentElement.clientHeight*0.9);
	height90= Math.min(height90, window.innerHeight - 20);
	oBox.style.maxHeight=height90+"px"

	//1.创建关闭按钮
	/* html: 
	<div id="cli_title" class="title"> 
		<b id="cli_on">-</b>
		Contents 
	</div>
	*/
	var oDivTitle=createElement("div", {
		"id":"cli_title",
		"class": "title",
	});
	//插入head行
	oDivTitle.appendChild(createElement("b", {"id":"cli_on"}, "-"));
	oDivTitle.appendChild(document.createTextNode("Contents"));
	oBox.appendChild(oDivTitle);
	
	//2. 生成a标签
	var arrHead=document.querySelectorAll(["h1", "h2", "h3", "h4", "h5", "h6"]);
	
	var oUl=document.createElement("ul");
	for(var i=1; i<arrHead.length; i++){
		//(1) 菜单链接
		var oH=arrHead[i];
		var text=oH.textContent;
		var oLi=document.createElement("li");
		var oA=document.createElement("a");
		var oSpan=document.createElement("span");
		//最多40个字
		oSpan.innerHTML=text.length>40? text.substr(0,38)+"...":text;
		oA.appendChild( oSpan );
		oA.setAttribute("href", "#"+i);
		//(1.2)添加事件：单击则刷新当前高亮
		oA.onclick=highlight_curent_munu;

		oLi.appendChild(oA);

		var classVal=oLi.getAttribute("class") || ""
		oLi.setAttribute("class", classVal.concat(" indent_" + oH.tagName.substring(1)) );

		oUl.appendChild( oLi );

		//(2)在原文h2等标题后插入a锚点，使用 my-data="anchor" 进行区分
		var oA2=document.createElement("a");
		oA2.setAttribute("name", i)
		oA2.setAttribute("my-data", "anchor");

		oH.parentNode.insertBefore(oA2, oH);
	}
	oBox.appendChild(oUl);

	//3.插入文档流
	document.body.appendChild(oBox);
}



// 窗口滚动时，高亮右侧当前菜单
// bug: step5, 最后一个标题不会高亮
function highlight_curent_munu(){
	//0. whether highlight the last header
	var flag=false;
	
	//1.scrollTop就是触发滚轮事件时滚轮的高度
	var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
	
	//2.右侧目录标题 ele
	var aSpan=$('rightMenu').getElementsByTagName("span");
	
	//3.正文标题 ele
	var aA= document.querySelectorAll("a[my-data]");
	
	//4.所有ele去样式
	for(var j=0;j<aSpan.length;j++){
		aSpan[j].parentElement.setAttribute("class","");
	}
	
	//5.遍历正文锚点
	for(var i=0; i<aA.length; i++){
		if(aA[i].offsetTop >= scrollTop+50){
			//6.当前A 标签加样式:当前应该是 浏览器顶端所在的head编号
			aSpan[i==0?0:i-1].parentElement.setAttribute("class","cur");
			flag=true;
			break;
		}
	}
	
	//6. highlight the last header
	if(!flag){
		//console.log("manual highlight the last header");
		aSpan[6].parentElement.setAttribute("class","cur");
	}
}


//右侧菜单放大与缩小
window.jslecture.flag=true; //true 右侧菜单 打开状态
var rightMenu_toggle=function(){
	var oMenu=$("rightMenu");
	var flag=window.jslecture.flag;
	if(flag){
		window.jslecture.height=getComputedStyle(oMenu)['height'];
	}
	//set
	oMenu.style.right = flag?'-270px':0;
	oMenu.style.height = flag?'30px':window.jslecture.height;
	this.innerHTML=flag?"+":"-";
	//
	window.jslecture.flag = !flag;
} 


function loadRCode(success){
	ajax('code/Functions.R', function(dat){
		// 替换字符串中的 '<' 字符
		dat = dat.replace(/</g, '&lt;'); //essential *
		dat = dat.replace(/</g, '&gt;'); //optional
		// 替换字符串 ##{**VolcanoPlot**}## 为 header 2
		dat = dat.replace(/##\{\*\*/g, '<h2>');
		dat = dat.replace(/\*\*\}##/g, '</h2>');

		// for header 1
		dat = dat.replace(/#\{\*\*/g, '<h1>');
		dat = dat.replace(/\*\*\}#/g, '</h1>');

		// insert to div
		document.getElementById("main_code").innerHTML=dat
		
		//加载完成后执行回调函数
		success();
	})
}

// add event one after another
addEvent(window, "load", function(){
	//加载R代码，传入(生成右下角目录的)回调函数
	loadRCode(function(){

		//1.创建右侧菜单
		createRightMenu();

		//2.绑定事件: 单击+-号，右侧菜单放大和缩小
		addEvent($("cli_on"), "click", rightMenu_toggle);
		//加载后，右侧菜单自动收缩
		$('cli_on').click();

		//3.注册事件: 滚轮时，高亮显示当前菜单
		//addEvent(window, "scroll", highlight_curent_munu);
		window.addEventListener("scroll", highlight_curent_munu, false);
		window.scrollBy(1, 1); //主动触发滚动，否则没有高亮	
	})

}, false);


</script>
